import { Alias } from '@rollup/plugin-alias'
import { Replacement } from '@rollup/plugin-replace'
import { Parser } from 'postcss'
import type {
    OutputOptions,
    RollupOptions,
    Plugin,
    ModuleFormat,
    RollupCache,
    PreserveEntrySignaturesOption,
    NullValue
} from 'rollup'
import { parseGlobOptions, ParseGlobResult } from '../utils/parse'

export type BabelTargetType =
    | 'es5'
    | 'es6'
    | 'node'
    | string
    | Array<string>
    | { [key: string]: string }

export type ScssModuleOption = {
    mode?: 'local' | 'global' | 'pure'
    naming?: string
    generateScopedName?: string | ((name: string, file: string, css: string) => string)
}

type UrlOptions = {
    alias?: Record<string, string>
    assetDir?: string
    inline?: boolean
    publicPath?: string
    hash?: boolean | string
    resolve?: any
}
export interface ExtractedData {
    /** CSS */
    css: string
    /** Sourcemap */
    map?: string
    /** Output name for CSS */
    name: string
}
export interface ImportOptions {
    /**
     * Provide custom resolver for imports
     * in place of the default one
     */
    resolve?: any
    /**
     * Aliases for import paths.
     * Overrides the global `alias` option.
     * - ex.: `{"foo":"bar"}`
     */
    alias?: Record<string, string>
    /**
     * Import files ending with these extensions.
     * Overrides the global `extensions` option.
     * @default [".css", ".pcss", ".postcss", ".sss"]
     */
    extensions?: string[]
}
export type ScssOptions = {
    include?: ReadonlyArray<string | RegExp> | string | RegExp | null
    exclude?: ReadonlyArray<string | RegExp> | string | RegExp | null
    extensions?: string[]
    dts?: boolean
    mode?:
        | 'inject'
        | ['inject']
        | ['inject', (varname: string, id: string) => string]
        | 'extract'
        | ['extract']
        | ['extract', string]
        | 'emit'
        | ['emit']
    namedExports?: boolean | ((name: string) => string)
    alias?: Record<string, string>
    modules?: boolean | ScssModuleOption
    autoModules?: boolean | RegExp | ((id: string) => boolean)
    minimize?: boolean
    sourceMap?: boolean | 'inline'
    parser?: string | Parser
    filename?: string
    plugins?: any[]
    sass?: {
        data?: string
        [key: string]: any
    }
    less?: {
        data?: string
        [key: string]: any
    }
    url?: boolean | UrlOptions
    use?: string[]
    onImport?: (code: string, id: string) => void
    onExtract?: (data: ExtractedData) => boolean
}
export type BuildOption = Partial<{
    isMinify: boolean
    target: BabelTargetType
    babelType: EnvironmentType
    jsxImportSource?: string
    babel: BabelPresetOptions
    style?: {
        entry?: string
        filename?: string
        exclude?: string[]
        ignore?: string | string[]
        inclueFile?: string[]
    }
}>
export type PatternInputItemOption = {
    pattern: string
    filename?: string | ((entryList: ParseGlobResult[]) => { [entryAlias: string]: string })
    ignore?: string | string[]
    inputConfig?: { [entryAlias: string]: string }
    patternOptions?: parseGlobOptions
}
export type PatternInputOption = PatternInputItemOption
export type InputOption = RollupOptions['input'] | PatternInputOption
export type OutputOption = OutputOptions & {
    formats?: ModuleFormat | (OutputOptions | ModuleFormat)[]
}

export type RollupConfigure = RollupOptions
export type RollupPlugin = Plugin

export type RollupConfigureItemProps = keyof RollupConfigure

export type ExternalItemOption =
    | string
    | RegExp
    | ((source: string, importer: string | undefined, isResolved: boolean) => boolean | NullValue)
export type ExternalOption = ExternalItemOption[] | ExternalItemOption

export interface RollifyConfigure {
    libType?: 'pattern' | 'original'
    entry?: InputOption
    output?: OutputOption
    external?: ExternalOption
    cache?: RollupCache | boolean
    preserveEntrySignatures?: PreserveEntrySignaturesOption
    alias?: Record<string, string> | Alias[]
    define?: Record<string, Replacement>
    scssModule?: ScssOptions
    build?: BuildOption
    declaration?: {
        tsconfigPath?: string
        declarationDir?: string
        input?: RollupOptions['input']
        output?: OutputOption
        entry?: InputOption
    }
}

export interface CommandLineConfigure {
    service: boolean
}
export type EnvironmentType =
    | 'react'
    | 'react-ts'
    | 'react-lib'
    | 'react-ts-lib'
    | 'preact'
    | 'preact-ts'
    | 'preact-lib'
    | 'preact-ts-lib'
    | 'h5'
    | 'h5-ts'
    | 'h5-lib'
    | 'h5-ts-lib'
    | 'node'
    | 'node-ts'
export type ReactVersion = '17' | '18' | number

export interface BabelPresetOptions {
    /** 项目环境类型 */
    type?: EnvironmentType
    /** 目标环境配置 */
    targets?: BabelTargetType
    /** 模块类型 */
    modules?: 'amd' | 'umd' | 'systemjs' | 'commonjs' | 'cjs' | 'esm' | false | 'auto'
    /** React版本 */
    reactVersion?: ReactVersion
    /** JSX导入源 */
    jsxImportSource?: string
    /** 是否为开发环境 */
    development?: boolean
    /** 显式控制是否使用transform-runtime插件 */
    useTransformRuntime?: boolean
}
